#ifndef _WX_VSCROLL_H_
#define _WX_VSCROLL_H_

#include "wx/panel.h"

class wxVScrolledWindow : public wxPanel {
  public:
    wxVScrolledWindow() { Init(); }
    wxVScrolledWindow( wxWindow *parent,wxWindowID id = wxID_ANY,const wxPoint& pos = wxDefaultPosition,
                       const wxSize& size = wxDefaultSize,long style = 0,const wxString& name = wxPanelNameStr ) {
      Init();
      ( void )Create( parent, id, pos, size, style, name );
    }
    bool Create( wxWindow *parent,wxWindowID id = wxID_ANY,const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize,long style = 0,const wxString& name = wxPanelNameStr ) {
      return wxPanel::Create( parent, id, pos, size, style | wxVSCROLL, name );
    }
    void SetLineCount( size_t count );
    bool ScrollToLine( size_t line );
    virtual bool ScrollLines( int lines );
    virtual bool ScrollPages( int pages );
    virtual void RefreshLine( size_t line );
    virtual void RefreshLines( size_t from, size_t to );
    int HitTest( wxCoord x, wxCoord y ) const;
    int HitTest( const wxPoint& pt ) const { return HitTest( pt.x, pt.y ); }
    virtual void RefreshAll();
    size_t GetLineCount() const { return m_lineMax; }
    size_t GetVisibleBegin() const { return m_lineFirst; }
    size_t GetVisibleEnd() const { return m_lineFirst + m_nVisible; }
    bool IsVisible( size_t line ) const{ return line >= GetVisibleBegin() && line < GetVisibleEnd(); }
    size_t GetFirstVisibleLine() const { return m_lineFirst; }
    size_t GetLastVisibleLine() const { return GetVisibleEnd() - 1; }
    virtual bool Layout();
  protected:
    virtual wxCoord OnGetLineHeight( size_t n ) const = 0;
    virtual void OnGetLinesHint( size_t ( lineMin ),size_t ( lineMax ) ) const { }
    virtual wxCoord EstimateTotalHeight() const;
    void OnSize( wxSizeEvent& event );
    void OnScroll( wxScrollWinEvent& event );
    #if wxUSE_MOUSEWHEEL
    void OnMouseWheel( wxMouseEvent& event );
    #endif
    size_t FindFirstFromBottom( size_t lineLast, bool fullyVisible = false );
    wxCoord GetLinesHeight( size_t lineMin, size_t lineMax ) const;
    void UpdateScrollbar();
    void RemoveScrollbar();
  private:
    void Init();
    size_t m_lineMax;
    wxCoord m_heightTotal;
    size_t m_lineFirst;
    size_t m_nVisible;

    #if wxUSE_MOUSEWHEEL
    int m_sumWheelRotation;
    #endif

    DECLARE_EVENT_TABLE()
    DECLARE_NO_COPY_CLASS( wxVScrolledWindow )
    DECLARE_ABSTRACT_CLASS( wxVScrolledWindow )
};

#endif
